/*
Kakine
ActionScript Framework
Copyright © 2011, PUNY, LLC.

This file is part of KAKINE.

KAKINE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

KAKINE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KAKINE.  If not, see <http://www.gnu.org/licenses/>.
*/ 
package com.puny.mvc.controllers
{
	import com.puny.mvc.BaseObject;
	import com.puny.mvc.MvcEvent;
	import com.puny.mvc.views.TransitionBaseView;
	
	import flash.events.Event;
	
	/**
	 * $Revision: 706 $<br/>
	 * This class handles <code>BaseObject</code> serially.
	 * After a <code>BaseObject</code> is completed, the next <code>BaseObject</code> will start. 
	 */
	public class WorkflowController extends Controller
	{
		private var _flow:Array
		
		/**
		 * Constructor. A serial task list is given.
		 * 
		 * @param tasks a list of <code>BaseObject</code> instances or class names which is processed serially.
		 * Instances and class names can be mixed. If a class name is given, it will be instantiated just before the instance is needed.
		 */
		public function WorkflowController(tasks:Array)
		{
			_flow = tasks;
			super();
		}
		
		final override public function afterOpen():void {
			workflowHandler();
		}
		
		/**
		 * This is invoked every time just before each <code>BaseObject</code> in the given list starts.
		 * If it's a class name instead of an instance, this will happen before instatiation.
		 * If it's an instance, this will happen before the instance is added to the stage.
		 */
		protected function beforeWork():void {}
		/**
		 * This is invoked just after all <code>BaseObject</code> were completed.
		 */
		protected function afterWorkflow():void {complete()}
		
		private function workflowHandler(event:Event=null):void {
			beforeWork();
			var instance:BaseObject;
			var obj:Object = _flow.shift();
			if (obj is Class) {
				instance = new obj();
			} else {
				instance = obj as BaseObject;
			}
			if (instance is TransitionBaseView) {
				instance.addEventListener(MvcEvent.READY, getMainObjectHandler);
			} else {
				buildUp(instance);
			}
			addChild(instance);
		}
		
		private function getMainObjectHandler(event:Event):void {
			var transition:TransitionBaseView = event.currentTarget as TransitionBaseView;
			buildUp(transition.mainView);
		}
		
		private function buildUp(instance:BaseObject):void {
			if (stage != null) {
				stage.focus = instance;
				instance.addEventListener(MvcEvent.COMPLETED, (_flow.length>0) ? workflowHandler: afterWorkflowHandler);
			}
		}
		
		private function afterWorkflowHandler(event:Event):void {
			
			afterWorkflow();
		}
		
		public function skip():void {
			var instance:BaseObject = getChildAt(0) as BaseObject;
			
			if (instance != null) {
				instance.removeEventListener(MvcEvent.COMPLETED, workflowHandler);
				instance.removeEventListener(MvcEvent.COMPLETED, afterWorkflow);
				instance.complete();
			}
//			while(_flow.length > 1) {
//				var obj:BaseObject = _flow.shift() as BaseObject;
//				obj.complete();
//			}
			workflowHandler();
		}
		
		override public function beforeClose():void {
			while(_flow.length > 1) {
				var obj:BaseObject = _flow.shift() as BaseObject;
				obj.complete();
			}
		}
	}
}